package zookeeper;

import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;

/**
 * 父类定义好全部方法，方法可以是具体已实现好的，也可以是抽象的，抽象方法在子类中实现（模板方法设计模式）
 */
public abstract class ZookeeperAbstractLock implements ExtLock {
	
	private static final String zkServer = "127.0.0.1:2181";
	protected ZkClient zkClient = new ZkClient(zkServer);
//	protected ZkClient zkClient = new ZkClient(zkServer, 4000, 4000, new SerializableSerializer());

	/**
	 * 获取锁：
	 *  	1、连接zkClient 创建一个/lock的临时节点
          	2、如果节点创建成果，直接执行业务逻辑，如果节点创建失败，进行等待 
	 */
	@Override
	public void getLock() {
		if(tryLock()) { // 获取到了锁
//			System.out.println(Thread.currentThread().getName() + "获取分布式锁成功了。");
		} else {
//			System.out.println(Thread.currentThread().getName() + "没有获取到分布式锁，等待锁。");
			waitLock(); // 等待锁
			
			getLock(); // 重新抢锁
		}
	}

	/**
	 * 主动释放锁
	 * 	1. 删除临时节点
	 */
	@Override
	public void unLock() {
		if(zkClient!=null) {
			zkClient.close(); // close方法关闭时候，延迟小
//			System.out.println(Thread.currentThread().getName() + "释放分布式锁成功了。");
		}
	}

	// 尝试获取锁（模板方法模式，具体实现交给子类完成）
    abstract boolean tryLock();

	//创建失败，等待锁（模板方法模式，具体实现交给子类完成）
    abstract void waitLock();
}
